package top.mingyi4cjh.cms.service;

import top.mingyi4cjh.cms.model.UserLoginModel;
import top.mingyi4cjh.cms.model.UserModel;

import java.security.NoSuchAlgorithmException;

/**
 * @author MingYi
 * @program cms
 * @create 2022/04/21 23:35
 */
public interface UserService {
    /**
     * 登录
     * 先根据userName进行取值，如不存在，则直接返回USER_LOGIN_FAIL。
     * 再根据取得的userId查询user_password表取得salt和密文。
     * 重新对明文和salt进行加密，若与数据库中字段不同，则返回USER_LOGIN_FAIL，否则为登陆成功。
     *
     * @param userName userName
     * @param password password
     * @return userModel
     * @throws NoSuchAlgorithmException 由MessageDigest.getInstance()产生
     */
    UserModel validateLogin(String userName, String password) throws  NoSuchAlgorithmException;

    /**
     * 记录登录信息
     * @param userLoginModel userInfo
     */
    void recordLogin(UserLoginModel userLoginModel);

    /**
     * 根据UserId获取User的信息
     * 通过传入的userId查询user_info获取数据，拼接返回
     *
     * @param id userId
     * @return userModel
     */
    UserModel getUserById(Long id);

    /**
     * 使用邮箱注册
     * 根据给定的邮箱进行注册，需要验证用户/邮箱是否已经存在，验证邮箱-OTP是否对应。
     *
     * @param userModel userModel
     * @param otpCode   验证码
     * @throws NoSuchAlgorithmException 由MessageDigest.getInstance()产生
     */
    void registerByEmail(UserModel userModel, String otpCode) throws  NoSuchAlgorithmException;

    /**
     * 使用手机号注册
     * 和registerByEmail 异曲同工，由于暂时没买手机短信服务，所以先空着，只是保留了该接口
     *
     * @param userModel userModel
     * @param otpCode   验证码
     * @throws NoSuchAlgorithmException 由MessageDigest.getInstance()产生
     */
    void registerByPhone(UserModel userModel, String otpCode) throws  NoSuchAlgorithmException;

    /**
     * 检查userName和email是否匹配，返回匹配结果
     * 判断userName和email是否匹配。
     * 先从redis中取数据，前缀是RedisPrefix.MAIL_NAME.getPrefix()，具体参见RedisPrefix.java， key是email。
     * 如果redis中没有该数据，则从mysql中取，无论从哪取得数据，都将重新在redis中存一份ttl为15min的值。
     * 最终返回取得的email的值和传入的email是否等值
     *
     * @param userName userName
     * @param email    email
     * @return true / false
     */
    boolean checkEmail(String userName, String email);

    /**
     * 检测email和otpCode是否匹配，返回userModel
     * 检查用户的身份信息，根据传入的email和otpCode进行。
     * 从redis中取得对应的otpCode信息，并与传入的值进行比对，不匹配则抛出异常。
     * 由于邮箱是唯一的，则从数据库中查询邮箱，并返回记录信息，存入userInfoDO，之后转换为userModel返回。
     * 将userId在redis中进行一次备份操作，key为前缀+userId，value为userName。
     *
     * @param email   email
     * @param otpCode 验证码
     * @return userModel
     */
    UserModel checkIdentify(String email, String otpCode);

    /**
     * 重置密码操作。
     * 需要验证用户的资格信息，是否该用户经历了前面的步骤，拿到了重置密码的资格。
     * 查询改资格需要从redis中查询相应前缀+userId的key是否存在，存在则有资格。
     * 确认用户有资格重置后，重新生成salt拼接在密码后方，并进行SHA256加密。
     * 最后将新生成的密文和salt更新入数据库。
     *
     * @param userId   userId
     * @param password password
     * @throws NoSuchAlgorithmException 由MessageDigest.getInstance()产生
     */
    void resetPassword(Long userId, String password) throws NoSuchAlgorithmException;

    /**
     * 清理重置密码过程中出现过的缓存信息
     * 根据传入的userId，删除本次操作中所有的缓存key。
     *
     * @param id userId
     */
    void cleanCacheOfReset(Long id);

    /**
     * 保存用户信息和otpCode的关系
     *
     * @param userModel userModel
     * @param otpCode   验证码
     */
    void saveIdOtp(UserModel userModel, String otpCode);

    /**
     * 通过id和otpCode验证身份
     *
     * @param id      userId
     * @param otpCode 验证码
     */
    void checkStatus(Long id, String otpCode);
}

